package com.base.common.http.server;


import android.content.Context;
import android.util.Log;

import com.base.common.http.handler.CompleteCallback;
import com.base.common.http.handler.FileSocketHandler;
import com.base.common.http.handler.HttpBusinessCallback;
import com.base.common.http.handler.HttpHandler;
import com.base.common.http.handler.SocketAdapterHandler;
import com.base.common.http.model.HttpConfigModel;
import com.base.common.http.util.CloseUtils;
import com.base.common.util.IpGetUtil;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;



/**
 * 微型嵌入式HttpServer
 * @ClassName MicroHttpServer
 * @Description: 微型嵌入式HttpServer
 * @Author cheng
 * @Date 2020/6/3
 * @Version V1.0
 **/
public final class MicroHttpServer {
    private static final String TAG = "MicroHttpServer";

    private static HttpServerProvider PROVIDER_INSTANCE = null;
    private static HttpConfigModel httpConfig;
    private static CompleteCallback completeCallback;
    private static HttpBusinessCallback httpBusinessCallback;
    private static boolean httpIsRunning = false;
    private static boolean socketIsRunning = false;

    public static void start(HttpConfigModel httpConfigModel, CompleteCallback _completeCallback){
        stop();
        httpConfig = httpConfigModel;
        completeCallback = _completeCallback;
        PROVIDER_INSTANCE = new HttpServerProvider();
        PROVIDER_INSTANCE.start();
    }

    public static void start(HttpConfigModel httpConfigModel, CompleteCallback _completeCallback, HttpBusinessCallback httpBusinessCallback){
        stop();
        httpConfig = httpConfigModel;
        completeCallback = _completeCallback;
        MicroHttpServer.httpBusinessCallback = httpBusinessCallback;
        PROVIDER_INSTANCE = new HttpServerProvider();
        PROVIDER_INSTANCE.start();
    }

    /**
     * 获取服务器是否正在运行 （Http 服务器 和 文件 socket 服务器）
     * @return 返回 boolean [true: 正在运行, false:未运行]
     */
    public static boolean getRunning(){
        return httpIsRunning && socketIsRunning;
    }

    /**
     * 获取Http服务器是否正在运行
     * @return 返回 boolean [true: 正在运行, false:未运行]
     */
    public static boolean getHttpServerRunning(){
        return httpIsRunning;
    }

    /**
     * 获取Socket服务器是否正在运行
     * @return 返回 boolean [true: 正在运行, false:未运行]
     */
    public static boolean getSocketServerRunning(){
        return socketIsRunning;
    }


    /**
     * 获取 http 服务器访问地址
     * @param context
     * @return
     */
    public static String getHttpServerUrl(Context context){
        String ip = IpGetUtil.getIPAddress(context);
        return String.format("http://%s:%d/", ip, httpConfig.getHttpPort());
    }

    /**
     * 获取 Socket 服务器访问地址 （用于文件发送）
     * @param context
     * @return
     */
    public static String getSocketServerUrl(Context context){
        String ip = IpGetUtil.getIPAddress(context);
        return String.format("%s:%d/", ip, httpConfig.getSocketPort());
    }


    public static void stop(){
        httpIsRunning = false;
        socketIsRunning = false;
        if(null != httpConfig) httpConfig = null;
        if(null == PROVIDER_INSTANCE) return;
        PROVIDER_INSTANCE.exit();
        PROVIDER_INSTANCE = null;
        Log.i(TAG,"MicroHttpServer stop ...");
    }


    private static class HttpServerProvider extends Thread{
        private boolean done = false;
        private boolean done2 = false;
        private ServerSocket serverSocket = null;

        private ServerSocket httpServerSocket = null;

        public HttpServerProvider() {

        }

        @Override
        public void run() {
            super.run();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        createHttpServer();
                    }
                }).start();

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        createSocketServer();
                    }
                }).start();
        }

        private void createHttpServer() {
            int port = httpConfig.getHttpPort();
            try {
                httpServerSocket = new ServerSocket(port);
                Log.i(TAG,"MicroHttpServer Start ...");
                String ipAddress = httpServerSocket.getInetAddress().getHostAddress();
                Log.i(TAG,String.format("http access url : http://%s:%d/", ipAddress, port));
                httpIsRunning = true;
                while (!done){
                    Socket socket = httpServerSocket.accept();
                    SocketAdapterHandler handler = new HttpHandler(socket, httpConfig, httpBusinessCallback);
                    handler.start();
                }
                Log.i(TAG,"MicroHttpServer Finish ...");
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                httpIsRunning = false;
                done = true;
                if(null != httpServerSocket){
                    CloseUtils.close(httpServerSocket);
                    httpServerSocket = null;
                }
            }

        }


        private void createSocketServer() {
            int port = httpConfig.getSocketPort();
            try {
                serverSocket = new ServerSocket(port);
                Log.i(TAG,"FileSocketServer Start ...");
                String ipAddress = serverSocket.getInetAddress().getHostAddress();
                Log.i(TAG,String.format("file socket server access url : %s:%d/", ipAddress, port));
                socketIsRunning = true;
                while (!done2){
                    Socket socket = serverSocket.accept();
                    SocketAdapterHandler handler = new FileSocketHandler(socket, httpConfig, completeCallback);
                    handler.start();
                }
                Log.i(TAG,"FileSocketServer Finish ...");
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                socketIsRunning = false;
                done2 = true;
                if(null != serverSocket){
                    CloseUtils.close(serverSocket);
                    serverSocket = null;
                }
            }
        }


        public void close(){
            try {
                done = true;
                done2 = true;
                socketIsRunning = false;
                httpIsRunning = false;
                if(null != httpServerSocket){
                    httpServerSocket.close();
                    httpServerSocket = null;
                }
                if(null != serverSocket){
                    serverSocket.close();
                    serverSocket = null;
                }

            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        public void exit(){
            close();
        }
    }
}
